#include "threadpool.h"

ThreadPool::ThreadPool(int num)
    : num_(num)
    , maxQueueSize_(0)
    , running_(false)
{
}

ThreadPool::~ThreadPool()
{
    if (running_) {
        stop();
    }
}

void ThreadPool::setMaxQueueSize(int maxSize)           //设置任务队列大小
{
    maxQueueSize_ = maxSize;
}

void ThreadPool::start()
{
    assert(threads_.empty());
    running_ = true;
    threads_.reserve(num_);
    for (int i = 0; i<num_; i++) {
        threads_.push_back(std::thread(std::bind(&ThreadPool::threadFunc, this)));          //绑定类成员
    }
}

void ThreadPool::stop()
{
    {
        std::unique_lock<std::mutex> ul(mutex_);                        //唤醒所有任务
    }

    for (auto &iter : threads_) {                                       //阻塞,等待所有任务结束
        iter.join();
    }
}

void ThreadPool::run(const Task &t)
{
    if (threads_.empty()) {
        t();
    }
    else {
        std::unique_lock<std::mutex> ul(mutex_);
        while (isFull()) {
            notFull_.wait(ul);
        }
        assert(!isFull());
        queue_.push_back(t);
        notEmpty_.notify_one();                       //队列有新任务,执行唤醒
    }
}

bool ThreadPool::isFull() const
{
    return maxQueueSize_ > 0 && queue_.size() >= maxQueueSize_;
}

void ThreadPool::threadFunc()
{
    //std::cout << "create id:" << std::this_thread::get_id() << std::endl;
    while (running_) {
        Task task(take());                                //创建线程
        if (task) {
            task();
        }
    }
    //std::cout << "thread id:" << std::this_thread::get_id() << std::endl;
}

ThreadPool::Task ThreadPool::take()
{
    std::unique_lock<std::mutex> ul(mutex_);
    while (queue_.empty() && running_) {                  //防止虚假消息
        notEmpty_.wait(ul);                                //阻塞,直到被唤醒
    }
    ThreadPool::Task task;
    if (!queue_.empty()) {
        task = queue_.front();
        queue_.pop_front();
        if (maxQueueSize_ > 0) {
            notFull_.notify_one();                          //唤醒一个线程
        }
    }
    return task;
}
